<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // https://juejin.cn/post/6946022649768181774?share_token=051a70f7-c167-4fc9-92b0-22dfe5e2b856
        class EventEmitter {
            constructor() {
                this.cache = {}
            }
            on(name, fn) {
                if (this.cache[name]) {
                    console.log('已经有车队了');
                    this.cache[name].push(fn);
                } else {
                    console.log('创建车队');
                    this.cache[name] = [fn]
                }
            }
            off(name, fn) {
                let tasks = this.cache[name]
                if (tasks) {
                    const index = tasks.findIndex(f => f === fn || f.callback === fn)
                    if (index >= 0) {
                        tasks.splice(index, 1)
                    }
                }
            }
            emit(name, once = false, ...args) {
                if (this.cache[name]) {
                    // 创建副本，如果回调函数内继续注册相同事件，会造成死循环
                    let tasks = this.cache[name].slice()
                    for (let fn of tasks) {
                        fn(...args)
                    }
                    if (once) {
                        console.log(`爱就一个字，我只说一次`);
                        delete this.cache[name]
                    }
                }
            }
        }

        // 测试
        let eventBus = new EventEmitter()
        let fn1 = function (name, age) {
            console.log(`${name} ${age}`)
        }
        let fn2 = function (name, age) {
            console.log(`hello, ${name} ${age}`)
        }
        eventBus.on('aaa', fn1)
        eventBus.on('aaa', fn2)
        eventBus.emit('aaa', false, '布兰', 12)
// '布兰 12'
// 'hello, 布兰 12'

    </script>
</body>

</html>